package models

import (
	"NewEdu/utils"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"reflect"
	"strings"
	"time"

	"github.com/beego/beego/v2/client/orm"
)

type TUser struct {
	Sn                     string     `orm:"column(sn);size(45);pk;" description:"学号"`
	Name                   string     `orm:"column(name);size(45);null" description:"姓名"`
	Pswd                   string     `orm:"column(pswd);size(45);null" description:"密码"`
	EnName                 string     `orm:"column(en_name);size(45);null" description:"英文名"`
	Desc                   string     `orm:"column(desc);size(145);null" description:"描述"`
	Sex                    string     `orm:"column(sex);size(5)" description:"性别"`
	Tel                    string     `orm:"column(tel);size(25)" description:"电话"`
	Birthday               string     `orm:"column(birthday);" description:"生日"`
	Qq                     string     `orm:"column(qq);size(45);null" description:"QQ"`
	Email                  string     `orm:"column(email);size(45);null" description:"邮箱"`
	Address                string     `orm:"column(address);size(95);null" description:"家庭住址"`
	FatherName             string     `orm:"column(father_name);size(45);null" description:"父亲名字"`
	MotherName             string     `orm:"column(mother_name);size(45);null" description:"母亲名字"`
	FatherTel              string     `orm:"column(father_tel);size(45);null" description:"父亲电话"`
	MotherTel              string     `orm:"column(mother_tel);size(45);null" description:"母亲电话"`
	TDepartId              int        `orm:"column(t_depart_id)" description:"所属班级"`
	Grade                  string     `orm:"column(grade);" description:"年级"`
	Ip1                    string     `orm:"column(ip1);size(45);null"`
	Ip2                    string     `orm:"column(ip2);size(45);null"`
	Ip3                    string     `orm:"column(ip3);size(45);null"`
	Role                   int8       `orm:"column(role);null" description:"身份:0是学生;1是老师"`
	Status                 string     `orm:"column(status);size(45);null" description:"状态"`
	ManagerID              int        `orm:"column(manager_id);null" description:"负责人的id"`
	Face                   string     `orm:"column(face);null" description:"头像"`
	Yicun                  string     `orm:"column(yicun);null" description:"一寸照"`
	Liangcun               string     `orm:"column(liangcun);null" description:"两寸照"`
	FaceData               string     `orm:"-"`
	YicunData              string     `orm:"-"`
	LiangcunData           string     `orm:"-"`
	Class                  string     `orm:"-"`
	LastFillAnswerTime     *time.Time `orm:"column(last_fill_answer_time);"   description:"姓名"`
	LastFillAnswerKind     int8       `orm:"column(last_fill_answer_kind);null" description:"密码"`
	LastFillAnswerTemplate string     `orm:"column(last_fill_answer_template);null" description:"0 普通访谈，1 出国访谈"`
}

func (t *TUser) TableName() string {
	return "t_user"
}

func init() {

	orm.RegisterModel(new(TUser))
}

// AddTUser insert a new TUser into database and returns
// last inserted Id on success.
func AddTUser(m *TUser) (id int64, err error) {
	// 加密密码
	if m.Pswd != "" {
		hashPassword, err := utils.HashPassword(m.Pswd)
		if err != nil {
			return 0, fmt.Errorf("密码加密失败: %v", err)
		}
		m.Pswd = hashPassword
	}

	o := orm.NewOrm()
	id, err = o.Insert(m)
	return
}

// GetTUserById retrieves TUser by Id. Returns error if
// Id doesn't exist
func GetTUserById(sn string) (v *TUser, err error) {
	ctx := context.Background()

	// 先从缓存获取
	cacheKey := fmt.Sprintf(utils.CacheKeyUser, sn)
	var itemJson []byte
	itemJson, err = utils.GetFromCache(ctx, cacheKey)
	if err == nil {
		v = new(TUser)
		err = json.Unmarshal(itemJson, v)
		if err == nil {
			return v, nil
		}
		utils.Warn("缓存数据反序列化失败", map[string]interface{}{
			"sn":    sn,
			"error": err.Error(),
		})
	}

	// 缓存未命中，从数据库查询
	o := orm.NewOrm()
	v = &TUser{Sn: sn}
	if err = o.Read(v); err == nil {
		// 存入缓存
		uploadUserInfo2Redis(ctx, v)
		return v, nil
	}
	return nil, err
}

func UserLogin(sn, pswd string) (v *TUser, jwt string, err error) {
	// 首先从数据库获取用户信息
	v, err = GetTUserById(sn)
	if err != nil {
		err = fmt.Errorf("用户不存在")
		return
	}

	// 验证密码 - 使用MD5验证（前端传过来的密码始终是MD5加密的）
	// 如果数据库中存储的是bcrypt加密的密码，则使用bcrypt验证
	// 如果数据库中存储的是MD5加密的密码，则使用MD5验证
	isValid := false
	
	// 首先尝试使用bcrypt验证（新方式）
	if utils.CheckPasswordHash(pswd, v.Pswd) {
		isValid = true
	} else {
		// 如果bcrypt验证失败，则尝试MD5验证（旧方式）
		// 前端传过来的密码始终是MD5加密的，所以直接比较
		if pswd == v.Pswd {
			isValid = true
		}
	}

	if !isValid {
		err = fmt.Errorf("密码错误")
		return
	}

	// 生成JWT token
	jwt, err = GetJwtString(utils.GetJWTExpire(), v.Sn, v.Name, v.Role)
	if err != nil {
		return
	}

	return v, jwt, nil
}
func QueryUsers(departid int, name, sn, tel string, offset int64, limit int64) (ml []*TUser, err error) {
	o := orm.NewOrm()

	// 使用Beego ORM的QueryBuilder来防止SQL注入
	qs := o.QueryTable(new(TUser))

	// 添加部门过滤条件
	qs = qs.Filter("t_depart_id", departid)

	// 安全地添加LIKE查询条件
	if len(name) > 0 {
		qs = qs.Filter("name__icontains", name)
	}
	if len(sn) > 0 {
		qs = qs.Filter("sn__icontains", sn)
	}
	if len(tel) > 0 {
		qs = qs.Filter("tel__icontains", tel)
	}

	// 只选择需要的字段
	_, err = qs.Limit(limit, offset).All(&ml, "sn", "name", "tel", "desc", "sex", "ip1", "t_depart_id",
		"last_fill_answer_time", "last_fill_answer_kind", "last_fill_answer_template")

	return
}

// GetAllTUser retrieves all TUser matches certain condition. Returns empty list if
// no records exist
func GetAllTUser(query map[string]string, fields []string, sortby []string, order []string,
	offset int64, limit int64) (ml []interface{}, err error) {
	o := orm.NewOrm()
	qs := o.QueryTable(new(TUser))
	// query k=v
	for k, v := range query {
		// rewrite dot-notation to Object__Attribute
		k = strings.Replace(k, ".", "__", -1)
		if strings.Contains(k, "isnull") {
			qs = qs.Filter(k, (v == "true" || v == "1"))
		} else {
			qs = qs.Filter(k, v)
		}
	}
	// order by:
	var sortFields []string
	if len(sortby) != 0 {
		if len(sortby) == len(order) {
			// 1) for each sort field, there is an associated order
			for i, v := range sortby {
				orderby := ""
				if order[i] == "desc" {
					orderby = "-" + v
				} else if order[i] == "asc" {
					orderby = v
				} else {
					return nil, errors.New("Error: Invalid order. Must be either [asc|desc]")
				}
				sortFields = append(sortFields, orderby)
			}
			qs = qs.OrderBy(sortFields...)
		} else if len(sortby) != len(order) && len(order) == 1 {
			for _, v := range sortby {
				orderby := ""
				if order[0] == "desc" {
					orderby = "-" + v
				} else if order[0] == "asc" {
					orderby = v
				} else {
					return nil, errors.New("Error: Invalid order. Must be either [asc|desc]")
				}
				sortFields = append(sortFields, orderby)
			}
		} else if len(sortby) != len(order) && len(order) != 1 {
			return nil, errors.New("Error: 'sortby', 'order' sizes mismatch or 'order' size is not 1")
		}
	} else {
		if len(order) != 0 {
			return nil, errors.New("Error: unused 'order' fields")
		}
	}

	var l []TUser

	qs = qs.OrderBy(sortFields...)
	if _, err = qs.Limit(limit, offset).All(&l, fields...); err == nil {
		if len(fields) == 0 {
			for _, v := range l {
				ml = append(ml, v)
			}
		} else {
			// trim unused fields
			for _, v := range l {
				m := make(map[string]interface{})
				val := reflect.ValueOf(v)
				for _, fname := range fields {
					m[fname] = val.FieldByName(fname).Interface()
				}
				ml = append(ml, m)
			}
		}
		return ml, nil
	}
	return nil, err
}

// UpdateTUser updates TUser by Id and returns error if
// the record to be updated doesn't exist
func UpdateTUserBySN(m *TUser) (err error) {
	o := orm.NewOrm()
	// fmt.Println(o, "=======m:", m)
	var num int64
	if num, err = o.Update(m, "name", "en_name", "tel", "desc", "birthday", "qq", "email", "address", "face", "yicun", "liangcun", `last_fill_answer_time`, `last_fill_answer_kind`, `last_fill_answer_template`); err == nil {
		fmt.Println("Number of records updated in database:", num)
	}
	uploadUserInfo2Redis(context.Background(), m)
	return
}

// DeleteTUser deletes TUser by Id and returns error if
// the record to be deleted doesn't exist
func DeleteTUser(sn string) (err error) {
	o := orm.NewOrm()
	v := TUser{Sn: sn}
	// ascertain id exists in the database
	if err = o.Read(&v); err == nil {
		var num int64
		if num, err = o.Delete(&TUser{Sn: sn}); err == nil {
			fmt.Println("Number of records deleted in database:", num)
		}
	}
	return
}

func LoadUser2Redis() error {
	o := orm.NewOrm()
	qs := o.QueryTable(new(TUser))

	var allUser []*TUser
	counts, err := qs.All(&allUser)
	if err != nil {

		return err
	}
	fmt.Println("载入 user 到redis中数为:", counts)
	ctx := context.Background()
	for _, item := range allUser {
		uploadUserInfo2Redis(ctx, item)
	}
	return nil
}

func uploadUserInfo2Redis(ctx context.Context, item *TUser) error {
	// 不缓存密码信息的用户对象
	userCache := *item
	// userCache.Pswd = "" // 不缓存密码

	itemJson, err := json.Marshal(userCache)
	if err != nil {
		utils.Error("用户信息序列化失败", map[string]interface{}{
			"sn":    item.Sn,
			"error": err.Error(),
		})
		return err
	}

	cacheKey := fmt.Sprintf(utils.CacheKeyUser, item.Sn)
	err = utils.SetToCache(ctx, cacheKey, itemJson, utils.CacheExpireUser)
	if err != nil {
		utils.Error("用户信息写入缓存失败", map[string]interface{}{
			"sn":    item.Sn,
			"error": err.Error(),
		})
		return err
	}

	return nil
}
